package cn.ambeius.backend.dm.pageCache;

import cn.ambeius.backend.dm.page.Page;
import cn.ambeius.backend.utils.Panic;
import cn.ambeius.common.Error;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;

public interface PageCache {
    
    public static final int PAGE_SIZE = 1 << 13;

    /**
     * 功能描述：新建一个数据页
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    int newPage(byte[] initData);

    /**
     * 功能描述：获取一个数据页
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    Page getPage(int pgno) throws Exception;

    /**
     * 功能描述：关闭
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    void close();

    /**
     * 功能描述：释放
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    void release(Page page);

    /**
     * 功能描述：截断数据？暂时不懂这个操作
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    void truncateByBgno(int maxPgno);

    /**
     * 功能描述：获取页码
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    int getPageNumber();

    /**
     * 功能描述：将缓存刷新到硬盘
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    void flushPage(Page pg);

    /**
     * 功能描述：创建一个数据到缓存
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    public static PageCacheImpl create(String path, long memory) {
        File f = new File(path + PageCacheImpl.DB_SUFFIX);
        try {
            if(!f.createNewFile()) {
                Panic.panic(Error.FileExistsException);
            }
        } catch (Exception e) {
            Panic.panic(e);
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
           Panic.panic(e);
        }
        return new PageCacheImpl(raf, fc, (int) memory / PAGE_SIZE);
    }

    /**
     * 功能描述：读取一个数据到缓存
     *
     * @author HeJiaWei
     * @date 22/01/2024
     */
    public static PageCacheImpl open(String path, long memory) {
        File f = new File(path + PageCacheImpl.DB_SUFFIX);
        if(!f.exists()) {
            Panic.panic(Error.FileNotExistsException);
        }
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
           Panic.panic(e);
        }
        return new PageCacheImpl(raf, fc, (int) memory / PAGE_SIZE);
    }
}